Linux中eventfd的使用

eventfd简介

eventfd是用来实现多进程或多线程之间的事件通知的,常见的事件通知机制除了eventfd外,还有条件变量和管道等 方式。

条件变量必须和互斥锁相结合使用,使用起来较麻烦,并且条件变量不能像eventfd一样为I/O事件驱动。

管道可以和I/O复用很好的融合,但是管道比eventfd多用了一个文件描述符,而且 管道内核还得给其管理的缓冲区,eventfd则不需要。

event的主要接口

eventfd的接口形式如下:

1
int eventfd(unsigned int initval, int flags);

eventfd()创建一个文件描述符,这个文件描述符用户可以通过等待其可读来实现事件通知,该通知靠内核来响应用户空间的应用事件。上述接口的第一个参数是由内核来保持的64位计数器,这个计算器由参数initval来初始化,一般设为0。

第二个参数flags可以为EFD_NONBLOCK或EFD_CLOEXEC。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <sys/eventfd.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
int fd;
uint64_t buffer;
void threadFunc(void) {
int t;
while (1) {
t = read(fd, &buffer, sizeof(buffer));
if (sizeof(buffer) < 8) {
printf("buffer错误\n");
}
printf("t = %11u buffer = %11u\n", t, buffer);
if (t == 8) {
printf("唤醒成功\n");
}
}
}
int main() {
uint64_t buf = 1;
int ret;
pthread_t tid;
if ((fd = eventfd(0, 0)) == -1) {
printf("创建失败\n");
}
if (pthread_create(&tid, NULL, threadFunc, NULL) < 0) {
printf("线程创建失败\n");
}
while (1) {
ret = write(fd, &buf, sizeof(buf));
if (ret != 8) {
printf("写错误\n");
}
sleep(2);
}
return 0;
}